#include "EnvironmentSphere.h"

EnvironmentSphere::EnvironmentSphere(void)
{
}

EnvironmentSphere::EnvironmentSphere(vec2 pCenter, float pRadius, int pNu, int pNv, string pEnvTexImagePath, GLuint pTexId ):
mSphereCenter(pCenter),
mSphereRadius(pRadius),
mNu(pNu),
mNv(pNv),
mEnvTextureImage(pEnvTexImagePath),
mTextureId(pTexId)
{
	setTextureParameters(pEnvTexImagePath);

	int nmbTriangles = 2 * (mNu - 1) * (mNv - 1), nVerts = mNu * mNv;
	float* vertices = new float[nVerts * 3];
	float* normals = new float[nVerts * 3];
	float* uv = new float[nVerts * 2];
	unsigned int* indexes = new unsigned int[nmbTriangles * 3];

	// Fill in vertices array
	int pp = 0, np = 0, uvp = 0, h = 0;
	int v, u;
	for(v = 0; v < mNv; v++)
	{
		float fv = (float) v / (float) (mNv - 1);
		for(u = 0; u < mNu; u++)
		{
			float fu = (float) u / (float) (mNu - 1);
			uv[uvp] = fu;
			uv[uvp + 1] = fv;
			parametricEval(fu, fv, pp, np, vertices, normals);
			pp += 3;
			np += 3;
			uvp += 2;
		}
	}

	// Fill in indexes array
	int ip = 0;
	for (v = 0; v < mNv - 1; ++v) 
	{
		for (u = 0; u < mNu - 1; ++u) 
		{
			indexes[ip++] = u + 1	+ (v + 1)	* mNu;
			indexes[ip++] = u + 1	+ v			* mNu;
			indexes[ip++] = u		+ v			* mNu;

			indexes[ip++] = u		+ (v + 1)	* mNu;
			indexes[ip++] = u + 1	+ (v + 1)	* mNu;
			indexes[ip++] = u		+ v			* mNu;
		}
	}


	glVertexPointer(3, GL_FLOAT, 0, vertices);
	glTexCoordPointer(2, GL_FLOAT, 0, uv);
	glNormalPointer( GL_FLOAT, 0, normals);

	mId = glGenLists(1);

	glNewList(mId, GL_COMPILE);
	glDrawElements(GL_TRIANGLES, 3 * nmbTriangles, GL_UNSIGNED_INT, indexes );		
	
	glEndList();


	//delete [] vertices;
	//delete [] normals;
}
EnvironmentSphere::~EnvironmentSphere(void)
{
}
void EnvironmentSphere::parametricEval(float u, float v, int offsetP, int offsetN, float* vertices, float* normals)
{
	float theta = (float) (Math::PI / 2) * u, phi = (float) (2 * Math::PI * v);
	vertices[ offsetP + 0] = mSphereRadius * (float) ( sin(theta) * sin(phi) );
	vertices[ offsetP + 1] = mSphereRadius * (float) ( sin(theta) * cos(phi) );
	vertices[ offsetP + 2] = mSphereRadius * (float) ( cos(theta) );

	normals[ offsetN + 0] = -vertices[offsetP + 0];
	normals[ offsetN + 1] = -vertices[offsetP + 1];
	normals[ offsetN + 2] = -vertices[offsetP + 2];
}

void EnvironmentSphere::drawEnvSphere()
{
	glBindTexture(GL_TEXTURE_2D, mTextureId);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_LINEAR);
	
	glTexImage2D(GL_TEXTURE_2D, 0, 3, mSurface->w, mSurface->h, 0, GL_BGR, GL_UNSIGNED_BYTE, mSurface->pixels);

		
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glRotatef(90.0, 0.0, 0.0, 1.0);

	glMatrixMode(GL_MODELVIEW);
	glCallList(mId);
}
void EnvironmentSphere::setTextureParameters(string pTextImagePath)
{
	mSurface = SDL_LoadBMP(pTextImagePath.c_str());
	if(!mSurface)
	{
		cerr << "Could not load texture : " << pTextImagePath << endl;
	}
	else
	{

	}
}

void EnvironmentSphere::setTextureId(GLuint pTextureId)
{
	mTextureId = pTextureId;
}
GLuint EnvironmentSphere::getTextureId()
{
	return mTextureId;
}